use honeybee::prelude::*;
use honeybee::Result;

use crate::users::UserCenter;

#[derive(Default)]
pub struct GmsgCacheActor {
    gmsgs: Vec<gmsg_db::GmsgDb>,
    user_center_addr: Option<Addr<UserCenter>>,
}

impl GmsgCacheActor {
    fn user_center(&self) -> &Addr<UserCenter> {
        self.user_center_addr.as_ref().unwrap()
    }

    async fn reload(&mut self) -> Result<()> {
        self.gmsgs.clear();
        self.gmsgs = gmsg_db::find_no_expire_messages().await?;
        Ok(())
    }
}

impl Service for GmsgCacheActor {}

#[async_trait::async_trait]
impl Actor for GmsgCacheActor {
    fn name(&self) -> &str {
        "GmsgCacheActor"
    }

    async fn started(&mut self, ctx: &mut Context<Self>) -> Result<()> {
        info!("{} started", self.name());
        let router = ctx.get_router().await?;
        router.register::<proto::NewGmsgNotify>();

        self.reload().await?;

        self.user_center_addr = UserCenter::from_registry().await?.into();

        Ok(())
    }

    async fn stopped(&mut self, _ctx: &mut Context<Self>) {
        info!("{} stoped", self.name());
    }
}

#[async_trait::async_trait]
impl Handler<NetMsg<proto::NewGmsgNotify>> for GmsgCacheActor {
    async fn handle(
        &mut self,
        _ctx: &mut Context<Self>,
        msg: NetMsg<proto::NewGmsgNotify>,
    ) -> Result<()> {
        let msg = msg.msg;
        if let Err(err) = self.reload().await {
            error!("NewGmsgNotify reload err:{}", err);
        }
        let _ = self.user_center().send(msg);
        Ok(())
    }
}

#[message(result = "Vec<gmsg_db::GmsgDb>")]
pub struct QueryGmsgs;
#[async_trait::async_trait]
impl Handler<QueryGmsgs> for GmsgCacheActor {
    async fn handle(
        &mut self,
        _ctx: &mut Context<Self>,
        _: QueryGmsgs,
    ) -> Result<Vec<gmsg_db::GmsgDb>> {
        let now = chrono::Local::now().timestamp();
        Ok(self
            .gmsgs
            .iter()
            .filter(|gmsg| gmsg.expire_time > now)
            .cloned()
            .collect())
    }
}
